package com.ruoyi.framework.socket;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;

import com.ruoyi.common.core.domain.entity.SysUser;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.corundumstudio.socketio.SocketIOClient;
import com.corundumstudio.socketio.SocketIOServer;

/**
 * SocketIO 服务实现
 *
 * @author jokerpan
 */
@Service(value = "socketIOService")
public class SocketIOServiceImpl implements SocketIOService {
    private static final Logger log = LoggerFactory.getLogger(SocketIOServiceImpl.class);

    // 用来存已连接的客户端
    public static Map<String, SocketIOClient> clientMap = new ConcurrentHashMap<>();

    // 保存用户自定义事件名称
    private static String SAVE_USER_EVENT = "save"; //保存用户
    private static String CLEAR_USER_EVENT = "clear"; //清除用户

    private static String BROADCAST = "broadcast"; //广播
    private static String SEND_MESSAGE_EVENT = "sendMessage"; //发送消息

    @Autowired
    private SocketIOServer socketIOServer;

    /**
     * Spring IOC容器创建之后，在加载SocketIOServiceImpl Bean之后启动
     *
     * @throws Exception
     */
    @PostConstruct
    private void autoStartup() throws Exception {
        start();
    }

    /**
     * Spring IOC容器在销毁SocketIOServiceImpl Bean之前关闭,避免重启项目服务端口占用问题
     *
     * @throws Exception
     */
    @PreDestroy
    private void autoStop() throws Exception {
        stop();
    }

    @Override
    public void start() {

        // 监听客户端连接
        socketIOServer.addConnectListener(client -> {
            log.info("======socket连接成功！======");
        });

        // 监听客户端断开连接
        socketIOServer.addDisconnectListener(client -> {
            log.info("======socket连接关闭！======");
        });

        /**
         * 监听客户端自定义事件
         */
        //保存用户
        socketIOServer.addEventListener(SAVE_USER_EVENT, String.class, (client, data, ackSender) -> {
            // 客户端推送`自定义`事件时，onData接受数据，这里是string类型的json数据，还可以为Byte[],object其他类型
            String userId = data;
            clientMap.put(userId, client);
            log.debug("------ID为：【" + userId + "】的用户加入连接------");
        });

        //清除用户
        socketIOServer.addEventListener(CLEAR_USER_EVENT, String.class, (client, data, ackSender) -> {
            String userId = data;
            if (clientMap.get(userId) != null) clientMap.remove(userId);
            log.debug("------ID为：【" + userId + "】的用户断开连接------");
        });

        //广播消息
        socketIOServer.addEventListener(BROADCAST, String.class, (client, data, ackSender) -> {
            String msg = data;
            //全体在线用户推送
            socketIOServer.getBroadcastOperations().sendEvent("message", msg);
        });

        socketIOServer.addEventListener(SEND_MESSAGE_EVENT, SysUser.class, (client, data, ackSender) -> {
            SysUser user = data;
            SocketIOClient socketIOClient = clientMap.get(user.getUserId().toString());
            if (socketIOClient != null) {
                // socketIOClient.sendEvent("message", user.getMsg());
                log.debug("触发消息推送");
            } else {
                log.debug("推送用户不在线！");
            }
        });

        socketIOServer.start();
    }

    @Override
    public void stop() {
        if (socketIOServer != null) {
            socketIOServer.stop();
            socketIOServer = null;
        }
    }

}